# -*- coding: utf-8 -*-
# @Time    : 2024/6/7 15:25
# @Author  : yujiahao
# @File    : 08_tuple_range.py
# @description:Python中的元组和Range


"""
Python、Java 和 Scala 中元组的介绍、使用方法、使用场景和注意事项

对于容器型数据类型list，无论谁都可以对其增删改查，那么有一些重要的数据放在list中是不安全的，
所以需要一种容器类的数据类型存放重要的数据，创建之初只能查看而不能增删改，这种数据类型就是元祖。

一、Python
2. 元组（Tuple）
    - 介绍：元组是一种有序的不可变集合，支持重复元素。元组在创建后不能修改，适用于存储不变的数据。
            俗称不可变的列表,又被成为只读列表,元祖也是python的基本数据类型之一,
            元组可以包含不同类型的元素，常用于函数返回多个值。
    - 使用方法：
        # 创建元组
        my_tuple = (1, 2, 3, 4, 5)

        # 单元素元组
        single_element_tuple = (1,)

        # 访问元素
        first_element = my_tuple[0]

        # 遍历元组
        for element in my_tuple:
            print(element)

        # 元组拆包
        a, b, c, d, e = my_tuple

    - 使用场景：需要存储有序的、不可变的数据集合时，如存储坐标、数据库记录、函数返回多个值等。
    - 注意事项：元组一旦创建不可修改，适合存储不需要改变的数据。元组的不可变性使其在需要安全传递数据时非常有用。

二、Java
2. 元组（Tuple）
    - 介绍：Java 标准库中没有直接支持元组，但可以通过第三方库（如 Apache Commons Lang、Javatuples）实现。
            元组是一种有限长度的有序集合，可以包含不同类型的元素。
    - 使用方法：
        import org.apache.commons.lang3.tuple.Pair;

        // 创建元组
        Pair<Integer, String> myTuple = Pair.of(1, "Hello");

        // 访问元素
        int firstElement = myTuple.getLeft();
        String secondElement = myTuple.getRight();

        // 遍历元组
        System.out.println(myTuple.getLeft());
        System.out.println(myTuple.getRight());

    - 使用场景：需要存储多个不同类型的值时，如返回多个结果、传递多个参数等。
    - 注意事项：使用第三方库时，需要额外引入依赖。元组的长度是固定的，适合存储少量不同类型的数据。

三、Scala
2. 元组（Tuple）
    - 介绍：Tuple 是一种有限长度的有序集合，可以包含不同类型的元素。Scala 的元组可以包含 2 到 22 个元素，
            常用于函数返回多个值或存储多种类型的值。
    - 使用方法：
        // 创建元组
        val myTuple = (1, "Hello", 3.14)

        // 访问元素
        val firstElement = myTuple._1
        val secondElement = myTuple._2
        val thirdElement = myTuple._3

        // 遍历元组
        myTuple.productIterator.foreach { element => println(element) }

        // 元组拆包
        val (a, b, c) = myTuple

    - 使用场景：需要存储多个不同类型的值时，如返回多个结果、传递多个参数等。
    - 注意事项：元组的长度是固定的，适合存储少量不同类型的数据。对于更复杂的数据结构，建议使用 case class。
"""


# todo 1、元组

'''
- 在 Python 中，元组是一种不可变的数据结构，这意味着一旦创建，元组中的元素就不能被修改、添加或删除。
- 然而，你仍然可以执行一些常见的操作，比如访问元素、查找元素、拼接元组等。
- 关于不可变, 注意: 这里元组的不可变的意思是子元素不可变. 而子元素内部的子元素是可以变, 这取决于子元素是否是可变对象.

【元组中如果只有一个元素. 一定要添加一个逗号, 否则就不是元组】
'''

# 1. 创建元组

# 创建一个空元组
empty_tuple = ()

# 创建一个包含多个元素的元组
my_tuple = (1, 2, 3, 4, 5)

# 创建一个单元素元组（注意逗号）
single_element_tuple = (1,)

# 2. 访问元素

# 访问元组中的元素
my_tuple = (1, 2, 3, 4, 5)
first_element = my_tuple[0]  # 1
last_element = my_tuple[-1]  # 5

# 3. 查找元素（index 和 count 方法）
# 查找元素的索引

my_tuple = (1, 2, 3, 4, 5)
index_of_3 = my_tuple.index(3)  # 2

# 统计元素出现的次数
count_of_2 = my_tuple.count(2)  # 1

# 4. 拼接元组

# 拼接两个元组
tuple1 = (1, 2, 3)
tuple2 = (4, 5, 6)
combined_tuple = tuple1 + tuple2  # (1, 2, 3, 4, 5, 6)

# 5. 元组重复

# 重复元组中的元素
my_tuple = (1, 2, 3)
repeated_tuple = my_tuple * 2  # (1, 2, 3, 1, 2, 3)

# 6. 元组切片
# 获取元组的子元组
my_tuple = (1, 2, 3, 4, 5)
sub_tuple = my_tuple[1:3]  # (2, 3)

# 7. 检查元素是否存在
# 检查元素是否在元组中
my_tuple = (1, 2, 3, 4, 5)
is_in_tuple = 3 in my_tuple  # True
is_not_in_tuple = 6 not in my_tuple  # True

# 8. 遍历元组
# 遍历元组中的元素
my_tuple = (1, 2, 3, 4, 5)
for element in my_tuple:
    print(element)


# 9. 获取元组长度
# 获取元组的长度
my_tuple = (1, 2, 3, 4, 5)
length = len(my_tuple)  # 5

# 10. 元组拆包
# 元组拆包
my_tuple = (1, 2, 3)
a, b, c = my_tuple
print(a, b, c)  # 1 2 3

# 11. 嵌套元组

'''' 就是将一些非常重要的不可让人改动的数据放在元祖中，只供查看。后期写项目的时候会有配置文件,配置文件中的不想让人修改的单个变量使用常量,如果是多个不想让人修改的就是用元组来存储'''
# 创建嵌套元组
nested_tuple = ((1, 2, 3), (4, 5, 6), (7, 8, 9))

# 访问嵌套元组中的元素
element = nested_tuple[1][2]  # 6

# 12. 转换为列表（以便进行增删改操作）
# 将元组转换为列表
my_tuple = (1, 2, 3, 4, 5)
my_list = list(my_tuple)

# 修改列表
my_list[0] = 10
my_list.append(6)
my_list.remove(3)

# 将列表转换回元组
my_tuple = tuple(my_list)

# 13. 使用内置函数
# 使用内置函数
my_tuple = (1, 2, 3, 4, 5)

# 获取最大值
max_value = max(my_tuple)  # 5

# 获取最小值
min_value = min(my_tuple)  # 1

# 计算和
sum_value = sum(my_tuple)  # 15

# 14. 排序元组（返回新的列表）
# 排序元组
my_tuple = (3, 1, 4, 2, 5)
sorted_list = sorted(my_tuple)  # [1, 2, 3, 4, 5]
sorted_tuple = tuple(sorted_list)  # (1, 2, 3, 4, 5)


print('''\n-----------------------------------☆☆☆分割线☆☆☆----------------------------------------\n''')



#todo  二、Range
'''
range 是 Python 中一个非常常用的内置函数，用于生成一个序列的数字。它通常用于循环中来迭代一系列的数字。
range 函数返回一个不可变的序列类型对象，而不是一个列表。



-语法：
    range(stop)
    range(start, stop[, step])
    start: 序列的起始值，包含在序列中。如果省略，默认值为 0。
    stop: 序列的结束值，不包含在序列中。
    step: 序列中数字之间的增量。如果省略，默认值为 1。
    数据范围：【左闭右开】

没啥意思，简单看一下就行
'''


# 基本用法

# 从 0 到 4 的序列（不包括 5）
for i in range(5):
    print(i)


# 指定起始值和结束值
# 从 2 到 5 的序列（不包括 6）
for i in range(2, 6):
    print(i)


# 指定步长
# 从 2 到 9 的序列，步长为 2
for i in range(2, 10, 2):
    print(i)


# 负步长
# 从 10 到 2 的序列，步长为 -2
for i in range(10, 1, -2):
    print(i)


# 使用 range 生成列表

'''虽然 range 返回的是一个 range 对象，而不是一个列表，但你可以使用 list() 函数将其转换为列表。'''

# 生成一个从 0 到 4 的列表
my_list = list(range(5))
print(my_list)

# range 对象的特性
'''
惰性求值：range 对象不会立即生成所有的数字，而是在需要时才生成。这使得 range 更加高效，特别是在处理非常大的范围时。
不可变：range 对象是不可变的，意味着你不能修改它。
'''
# 常见用法

# 迭代列表的索引
my_list = ['a', 'b', 'c', 'd']
for i in range(len(my_list)):
    print(f"Index: {i}, Value: {my_list[i]}")

# 输出:
# Index: 0, Value: a
# Index: 1, Value: b
# Index: 2, Value: c
# Index: 3, Value: d

# 反向迭代
for i in range(10, 0, -1):
    print(i)
# 输出: 10 9 8 7 6 5 4 3 2 1





# 练习

# 1. 利用 for 循环和 range 打印出下面列表的索引
li = ["alex", "WuSir", "ritian", "barry", "wenzhou"]

for i in range(len(li)):
    print(i)

# 2. 利用 for 循环和 range 找出 100 以内所有的偶数并将这些偶数插入到一个新列表中
even_numbers = []

for i in range(101):
    if i % 2 == 0:
        even_numbers.append(i)

print(even_numbers)


# 3. 利用 for 循环和 range 找出 50 以内能被 3 整除的数，并将这些数插入到一个新列表中
divisible_by_three = []

for i in range(50):
    if i % 3 == 0:
        divisible_by_three.append(i)

print(divisible_by_three)

# 4. 利用 for 循环和 range 从 100 到 1，倒序打印
for i in range(100, 0, -1):
    print(i)

# 5. 利用 for 循环和 range 将 1-30 的数字依次添加到一个列表中，并循环这个列表，将能被 3 整除的数改成 *
numbers = list(range(1, 31))

for i in range(len(numbers)):
    if numbers[i] % 3 == 0:
        numbers[i] = '*'

print(numbers)